#pragma once
#include <memory>
#include <string>
namespace xncc {
namespace user {
#ifndef GITVISION_VER
#    define GITVISION_VER ""
#endif

#ifndef COMPILE_TIME
#    define COMPILE_TIME ""
#endif
    class EventEngine;
    class ServerApplication
    {
      public:
        /*
            自主设置配置文件 不设置 则使用默认 ../conf/conf.json
            自主设置配置 可以设置json字符串
            两个都设置 优先启动配置文件
        */
        explicit ServerApplication(const std::string& f = "", const std::string& cfg = "");

        ServerApplication(const ServerApplication&)             = delete;
        ServerApplication(const ServerApplication&&)            = delete;
        ServerApplication& operator=(const ServerApplication&)  = delete;
        ServerApplication& operator=(const ServerApplication&&) = delete;

        virtual ~ServerApplication();
        /*
            初始化 run 会调用init
            init 一般需要做的事情是 创建引擎 并添加到引擎列表中
        */
        virtual void init() {};
        /*
            添加事件引擎
        */
        static void addEventengine(const std::shared_ptr<EventEngine>& engine);
        /*
            服务启动
        */
        int run(int argc, const char** argv);  // must be called

        /*
            服务停止
        */
        static void stop();
    };

    // 如果想在run之前捕获命令行参数 可以修改XNCC_APP_MAIN 宏

#define XNCC_APP_MAIN(App)                                                                                             \
    int main(int argc, const char** argv)                                                                              \
    {                                                                                                                  \
        if (argc >= 2) {                                                                                               \
            if (strncasecmp(argv[1], "-v", 2) == 0 || strncasecmp(argv[1], "--version", 9) == 0) {                     \
                printf("git-commit:%s\n", GITVISION_VER);                                                              \
                printf("compile-time:%s\n", COMPILE_TIME);                                                             \
                return 0;                                                                                              \
            }                                                                                                          \
        }                                                                                                              \
        std::unique_ptr<App> pApp{new App()};                                                                          \
        try {                                                                                                          \
            pApp->run(argc, argv);                                                                                     \
        }                                                                                                              \
        catch (const std::exception& ex) {                                                                             \
            printf("expection occured:  %s\n", ex.what());                                                             \
        }                                                                                                              \
        catch (...) {                                                                                                  \
            printf("unkown expection occured \n");                                                                     \
        }                                                                                                              \
        return 0;                                                                                                      \
    }
}  // namespace user
}  // namespace xncc